package com.topdt.jbpm.web.servlet.action;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import com.thx.common.util.ThreadLocalContext;
import com.topdt.jbpm.Constants;
import com.topdt.jbpm.WorkflowException;
import com.topdt.jbpm.form.Document;
import com.topdt.jbpm.form.FormUI;
import com.topdt.jbpm.identity.User;
import com.topdt.jbpm.model.Todo;
import com.topdt.jbpm.service.ActorResp;
import com.topdt.jbpm.service.EndResp;
import com.topdt.jbpm.service.OutComeResp;
import com.topdt.jbpm.service.SubmitResp;
import com.topdt.jbpm.service.cmd.JumpResult;
import com.topdt.jbpm.service.cmd.StartResult;
import com.topdt.jbpm.service.cmd.SubmitResult;
import com.topdt.jbpm.web.servlet.JbpmServlet;

/**
 * 工作流转相关（从JbpmServlet中迁移过来）
 *
 * @author balancejia
 *
 */
public class EngineAction extends JbpmBaseAction {

  public EngineAction(JbpmServlet servlet) {
    super(servlet);
  }

  /**
   * 启动工作
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void start(HttpServletRequest request, HttpServletResponse response) throws Exception {

    start(request, response, false);
  }

  private void start(HttpServletRequest request, HttpServletResponse response, boolean fromMobile)
      throws Exception {

    String resultJson = "{result:";

    String appId = request.getParameter(Constants.APPID_KEY);
    String businesskey = request.getParameter(Constants.BUSINESS_KEY);

    User user = (User) ThreadLocalContext.get(Constants.USER_KEY);

    String starter = user.getId();
    if (StringUtils.isEmpty(appId)) {
      resultJson = resultJson + Constants.APPID_KEY + "是空的}";
      responseJson(response, resultJson);
    } else if (StringUtils.isEmpty(starter)) {
      resultJson = resultJson + Constants.USER_KEY + "是空的}";
      responseJson(response, resultJson);
    } else {
      StartResult result = getJbpmService().startWork(appId, starter, null);
      String workId = (String) result.getWorkId();
      String activityName = (String) result.getActivityName();

      if (fromMobile) {
        logger.info("\n启动工作业务逻辑完成，开始组装表单......");
        FormUI ui = getJbpmService().assembleForm(workId);
        logger.info("\n......组装表单完成");

        logger.info("\n启动工作业务逻辑完成，开始调用 FormUI 响应客户端......");
        ui.response(request, response);
      } else {
        responseRedirec(request, response, "../work/getWorkByWorkId?workId=" + workId + "&businesskey="
            + businesskey);
      }
    }
  }

  /**
   *
   * 建立日期 : 2013-7-20 下午03:24:11<br>
   * 作者 : shiyan<br>
   * 描述 :客户端的起草工作
   */
  public void startM(HttpServletRequest request, HttpServletResponse response) throws Exception {
    start(request, response, true);
  }

  /**
   * 提交工作
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void submitWork(HttpServletRequest request, HttpServletResponse response) throws Exception {

    String workId = request.getParameter(Constants.WORKID_KEY);

    User user = (User) ThreadLocalContext.get(Constants.USER_KEY);
    String userId = user.getId();
    String todoId = request.getParameter("todoId");

    // --如果todoId==null 根据workId和toUser 来查找代办
    if (todoId == null || "".equals(todoId)) {
      Todo todo = getJbpmService().findTodoByWorkAndUser(workId, userId);
      todoId = todo.getTodoId();
    }
    Document doc = null;
    try {
      doc = getJbpmService().saveForm(workId, request.getParameterMap(), todoId);
    } catch (Exception e) {
      e.printStackTrace();
      EndResp resp = new EndResp();
      resp.setMessage("保存业务数据异常！");
      responseJson(response, resp);
      return;
    }
    // 当前环节的最后一个待办
    if (isLastTodo(todoId)) {
      OutComeResp outComes = getJbpmService().getOutcomes(todoId);
      // 只有一个出口路径
      if (outComes != null && outComes.size() == 1) {
        if (outComes.hasBackOut() || outComes.hasRestartOut()) {
          EndResp resp = new EndResp();
          JumpResult jumpResult = getJbpmService().goBackWork(todoId);
          String destAct = jumpResult.getDestActivity();
          String message = "已退回到【" + destAct + "：";
          List<User> users = jumpResult.getDestUsers();
          for (User u : users) {
            message += u.getName() + "，";
          }
          if (users.size() > 0) {
            message = message.substring(0, message.length() - 1);
          }
          message += "】环节！";
          resp.setMessage(message);
          responseJson(response, resp);
        } else {
          // 是否需要选人，如果要选人返回页面让用户选择环节执行人员
          if (!isNeedSetActor(todoId, request, response)) {
            endSubmit(todoId, null, outComes.getUniqueOut(), null, null, response);
          }
        }
        // 多个出口返回页面让用户选择出口
      } else if (outComes != null && outComes.size() > 1) {
        responseJson(response, outComes);
      } else {
        if (!isNeedSetActor(todoId, request, response)) {
          endSubmit(todoId, null, null, null, null, response);
        }
      }
    } else {
      endSubmit(todoId, null, null, null, null, response);
    }
  }

  /**
   *
   * 建立日期 : 2013-7-11 上午10:53:50<br>
   * 作者 : shiyan<br>
   * 描述 :
   */
  public void submitFreeWork(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    String workId = request.getParameter(Constants.WORKID_KEY);
    Document doc = null;
    try {
      doc = getJbpmService().saveForm(workId, request.getParameterMap(), null);
    } catch (Exception e) {
      e.printStackTrace();
      EndResp resp = new EndResp();
      resp.setMessage("保存业务数据异常！");
      responseJson(response, resp);
      return;
    }

    User user = (User) ThreadLocalContext.get(Constants.USER_KEY);
    String userId = user.getId();
    String todoId = request.getParameter("todoId");

    // --如果todoId==null 根据workId和toUser 来查找代办
    if (todoId == null || "".equals(todoId)) {
      Todo todo = getJbpmService().findTodoByWorkAndUser(workId, userId);
      todoId = todo.getTodoId();
    }

    String users = request.getParameter("users");
    if (users != null && !"".equals(users)) {
      // --继续流转
      Map<String, String> mUsers = new HashMap<String, String>();
      mUsers.put("users", users);
      endSubmit(todoId, doc, null, mUsers, null, response);
    } else {
      // --结束
      endSubmit(todoId, doc, null, null, null, response);
    }
  }

  /**
   * 提交路径
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void submitOutCome(HttpServletRequest request, HttpServletResponse response)
      throws Exception {

    String todoId = request.getParameter("todoId");

    String outCome = request.getParameter("outCome");

    if (outCome != null && !outCome.equals(""))
      getJbpmService().saveOutComeForTodo(todoId, outCome);
    else
      outCome = null;

    if (!isNeedSetActor(todoId, request, response)) {
      endSubmit(todoId, null, outCome, null, null, response);
    }
  }

  /**
   * 提交选择的活动参与者
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void submitActor(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    // fengjinshou 20160726设置编码
    request.setCharacterEncoding("utf-8");
    response.setCharacterEncoding("utf-8");
    String receivedActors = request.getParameter("actors");
    String todoId = request.getParameter("todoId");
    Map<String, String> users = new HashMap<String, String>();
    for (String ss : receivedActors.split(";")) {
      if (ss != null && !"".equals(ss)) {
        String[] s = ss.split(":");
        users.put(s[0], s[1]);
      }
    }
    getJbpmService().saveActorForTodo(todoId, receivedActors);

    String outCome = getJbpmService().getOutcomesOfTodo(todoId);

    endSubmit(todoId, null, outCome, users, null, response);
  }

  private boolean isNeedSetOutCome(String todoId, HttpServletRequest request,
      HttpServletResponse response) throws IOException {
    OutComeResp outComes = getJbpmService().getOutcomes(todoId);
    if (outComes != null) {
      if (outComes.size() == 1 && (outComes.hasBackOut() || outComes.hasRestartOut())) {
        JumpResult jumpResult = getJbpmService().goBackWork(todoId);
        responseJson(response, jumpResult);
        return false;
      } else {
        responseJson(response, outComes);
        return true;
      }
    } else
      return false;
  }

  private boolean isLastTodo(String todoId) {
    List<Todo> todos = getJbpmService().getOtherTodo(todoId);
    if (todos.size() == 0) {
      return true;
    } else {
      return false;
    }
  }

  private boolean isNeedSetActor(String todoId, HttpServletRequest request,
      HttpServletResponse response) throws IOException {

    Todo todo = getJbpmService().getTodoById(todoId);
    if (todo.getTaskId() == null) {
      try {
        request.getRequestDispatcher("selectUser.jsp").forward(request, response);
      } catch (ServletException e) {
        logger.error("", e);
        responseError(response, "forward to ");
      }
      return true;
    } else {

      // 判断是否需要选择人员
      ActorResp actors = getJbpmService().getFutureActors(todoId);

      if (actors != null) {
        responseJson(response, actors);
        return true;
      } else
        return false;
    }
  }

  private void endSubmit(String todoId, Document doc, String outCome, Map<String, String> users,
      Map<String, Object> vars, HttpServletResponse response) throws IOException {

    EndResp resp = new EndResp();
    try {
      SubmitResult result = getJbpmService().submitWork(todoId, doc, outCome, users, vars);
      String message = "";
      if (result.isEnd()) {
        message = "任务已提交，流程已结束！";
      } else if (result.isNext()) {
        message = result.spellNextMsg();
      } else if (result.isPauseConcurrence()) {
        message = result.getMessage();
      } else if (result.isPauseSeq()) {
        String nextActor = result.getNextActor();
        if (nextActor != null) {
          User user = getIdService().getUserById(nextActor);
          message = "任务已提交，[ " + user.getName() + " ]可以开始处理本环节的任务。";
        } else {
          message = "任务已提交，本环节还有其他人的任务没有处理！";
        }
      } else if (result.isWaitingMultiOut()) {
        message = "任务已提交，你的任务属于并行流程中的分支任务，当前还有其他分支任务没有结束！";
      } else if (result.isFreeResult()) {
        if (result.getType().equals(SubmitResult.TYPE_FREE_END)) {
        }
        message = result.getMessage();
      }
      resp.setMessage(message);
      resp.setTodoId(todoId);
    } catch (WorkflowException e) {
      logger.error("工作流提交异常", e);
      resp.setType(SubmitResp.TYPE_ERROR);
      resp.setMessage(e.getMsg());
      resp.setTodoId(todoId);
    } catch (Exception e) {
      logger.error("工作流提交异常", e);
      resp.setType(SubmitResp.TYPE_ERROR);
      resp.setMessage("提交异常!");
      resp.setTodoId(todoId);
    }
    responseJson(response, resp);
  }

  /**
   * 抢占工作
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void preemptTodo(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    String todoId = request.getParameter("todoId");
    if (todoId == null || "".equals(todoId)) {
      String workId = request.getParameter(Constants.WORKID_KEY);
      User user = (User) ThreadLocalContext.get(Constants.USER_KEY);
      String userId = user.getId();
      Todo todo = getJbpmService().findTodoByWorkAndUser(workId, userId);
      todoId = todo.getTodoId();
    }
    Map<String, String> msg = new HashMap<String, String>();

    String message = "抢占成功！";
    String type = "success";
    try {
      getJbpmService().takeTodo(todoId);
    } catch (Exception e) {
      message = "抢占失败！该工作别人已抢占，本页面将关闭！";
      type = "fail";
    }
    msg.put("message", message);
    msg.put("type", type);
    responseJson(response, msg);
  }


  /**
   * 获取可退回的环节
   */
  public void getPreTask(HttpServletRequest request, HttpServletResponse response) throws Exception {
    String todoId = request.getParameter("todoId");
    JumpResult result = getJbpmService().getPreTask(todoId);
    responseJson(response, result);
  }

  /**
   * 退回工作
   */
  public void goBackWork(HttpServletRequest request, HttpServletResponse response) throws Exception {
    String todoId = request.getParameter("todoId");
    JumpResult jumpResult = getJbpmService().goBackWork(todoId);
    responseJson(response, jumpResult);
  }


  /**
   * @Description : 退回到某个节点
   * @Method_Name : goOtherBackWork
   * @param request
   * @param response
   * @throws Exception
   * @return : void
   * @Creation Date : 2015年1月5日 下午4:05:23
   * @version : v1.00
   * @Author : calonlan
   *
   * @Update Date :
   * @Update Author :
   */
  public void goOtherBackWork(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    String todoId = request.getParameter("todoId");
    JumpResult jumpResult = getJbpmService().goOtherBackWork(todoId);
    responseJson(response, jumpResult);
  }

  /**
   * 退回起草
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void restartWork(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    String todoId = request.getParameter("todoId");
    JumpResult jumpResult = getJbpmService().restartWork(todoId);
    responseJson(response, jumpResult);
  }

  /**
   * 取得出口
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void getOutcomes(HttpServletRequest request, HttpServletResponse response)
      throws Exception {

  }

  /**
   * 取得后面活动处理人
   *
   * @param request
   * @param response
   * @throws Exception
   */
  public void getFutureActors(HttpServletRequest request, HttpServletResponse response)
      throws Exception {

  }

}
